﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using Newtonsoft.Json;
using System.Configuration;
using Newtonsoft.Json.Converters;
using System.Security.Cryptography;
using System.Web.Script.Serialization;
using System.Data.OleDb;

namespace GongZuo.Common
{
   public static class Utils
    {
        #region JSON序列化及反序列化

        public static string JsonSerialize(object value)
        {
            IntDateTimeConverter timeConverter = new IntDateTimeConverter();
            return JsonConvert.SerializeObject(value, timeConverter).Replace("\":null", "\":\"\"");
        }

        public static string JsonSerialize2(object value)
        {
            IsoDateTimeConverter timeFormat = new IsoDateTimeConverter();
            timeFormat.DateTimeFormat = "yyyy-MM-dd HH:mm:ss";
            return JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.Indented, timeFormat).Replace("\": null", "\":\"\"");
        }

        public static T JsonDeserialize<T>(string value)
        {
            DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0);
            foreach (Match m in Regex.Matches(value, @"[:][1]\d{9}")) //date["][:]\d{1,10}[,-}]
            {
                string a = m.Value;
                value = value.Replace(a, ":\"" + dt.AddSeconds(long.Parse(a.TrimStart(':'))).ToString("yyyy-MM-dd HH:mm:ss") + "\"");
            }

            if (string.IsNullOrWhiteSpace(value))
            {
                return default(T);
            }
            return JsonConvert.DeserializeObject<T>(value);
        }

        public static T DeserializeAnonymousType<T>(string jsonString, T anonymousTypeObject)
        {
            return JsonConvert.DeserializeAnonymousType(jsonString, anonymousTypeObject);
        }

        #endregion

        #region 取得IP地址
        public static string GetIP()
        {
            string result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            if (string.IsNullOrEmpty(result))
                result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            if (string.IsNullOrEmpty(result))
                result = HttpContext.Current.Request.UserHostAddress;
            if (string.IsNullOrEmpty(result) || !IsIP(result))
                return "127.0.0.1";
            return result;
        }
        public static bool IsIP(string ip)
        {
            return Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
        }
        #endregion

        #region 取得webconfig中的AppSettings
        /// <summary>
        /// 取得appsetting 不加入缓存
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetAppSettings(string key)
        {
            return System.Configuration.ConfigurationManager.AppSettings[key];
        }
        /// <summary>
        /// 取得appsetting 并加入缓存
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetAppSetting(string key)
        {
            object oValue = CacheManager.Get("AppSetting" + key);
            if (null != oValue)
            {
                return oValue.ToString();
            }
            //return System.Configuration.ConfigurationManager.AppSettings[key];
            string value = GetAppSettings<string>(GetStr, "", key);
            CacheManager.Insert("AppSetting" + key, value, 86400);
            return value;
        }
        /// <summary>
        /// 取得appsetting 并加入缓存 并加入默认值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetAppSetting(string key, string defaultValue)
        {
            object oValue = CacheManager.Get("AppSetting" + key);
            if (null != oValue)
            {
                return oValue.ToString();
            }
            //return System.Configuration.ConfigurationManager.AppSettings[key];
            string value = GetAppSettings<string>(GetStr, defaultValue, key);
            CacheManager.Insert("AppSetting" + key, value, 86400);
            return value;
        }

        /// <summary>
        ///  取得appsetting
        /// </summary>
        // GetAppSettings<bool>(bool.Parse, () => false, "EnableAzureWebTrace");  
        //原来是 Func<T> defaultTValueFunc  ，我认为直接加个默认值就行了 没有必要用委托
        // GetAppSettings<bool>(bool.Parse, false, "EnableAzureWebTrace")
        public static T GetAppSettings<T>(Func<string, T> parseFunc, T defaultTValue, string key)
        {
            try
            {
                string rawConfigValue = ConfigurationManager.AppSettings[key];
                return !string.IsNullOrEmpty(rawConfigValue) ? parseFunc(rawConfigValue) : defaultTValue;
            }
            catch (ConfigurationException)
            {
                return default(T);
            }
        }
        //没啥用，只是为了有些方法中，将某些委托当了参数，必须有个方法，比如楼上
        public static string GetStr(string value)
        {
            return value;
        }
        #endregion

        #region 返回相对相对根目录地址

        public static string ResolveUrl(string relativeUrl)
        {

            if (string.IsNullOrWhiteSpace(relativeUrl))
            {
                throw new ArgumentNullException("relativeUrl");
            }

            if (relativeUrl.Length == 0 || relativeUrl[0] == '/' || relativeUrl[0] == '\\')
            {
                return relativeUrl;
            }

            int idxOfScheme = relativeUrl.IndexOf(@"://", StringComparison.Ordinal);
            if (idxOfScheme != -1)
            {
                int idxOfQM = relativeUrl.IndexOf('?');
                if (idxOfQM == -1 || idxOfQM > idxOfScheme) return relativeUrl;
            }

            StringBuilder sbUrl = new StringBuilder();
            sbUrl.Append(HttpRuntime.AppDomainAppVirtualPath);
            if (sbUrl.Length == 0 || sbUrl[sbUrl.Length - 1] != '/') sbUrl.Append('/');

            // found question mark already? query string, do not touch!
            bool foundQM = false;
            bool foundSlash; // the latest char was a slash?
            if (relativeUrl.Length > 1
                && relativeUrl[0] == '~'
                && (relativeUrl[1] == '/' || relativeUrl[1] == '\\'))
            {
                relativeUrl = relativeUrl.Substring(2);
                foundSlash = true;
            }
            else foundSlash = false;
            foreach (char c in relativeUrl)
            {
                if (!foundQM)
                {
                    if (c == '?') foundQM = true;
                    else
                    {
                        if (c == '/' || c == '\\')
                        {
                            if (foundSlash) continue;
                            else
                            {
                                sbUrl.Append('/');
                                foundSlash = true;
                                continue;
                            }
                        }
                        else if (foundSlash) foundSlash = false;
                    }
                }
                sbUrl.Append(c);
            }

            return sbUrl.ToString();
        }

        public static string GetUrl(string url)
        {
            if (string.IsNullOrWhiteSpace(url))
            {
                return "#";
            }
            else
            {
                return Utils.ResolveUrl("~/" + url);
            }

        }
        #endregion

        #region  获取域名

        public static string GetDoMain()
        {
            string url = HttpContext.Current.Request.Url.ToString();

            int pos = url.IndexOf("/", 8);

            return url.Substring(0, pos);

        }

        #endregion

        #region 字符串处理
        /// <summary>
        /// 取得like时的行政区编码
        /// </summary>
        /// <param name="OrgCode"></param>
        /// <returns></returns>
        public static string GetLikeOrg(string OrgCode)
        {
            return (OrgCode + "A").Replace("0000A", "").Replace("00A", "").TrimEnd('A');
        }
        #endregion

        #region 时间转化为数字
        public static int ConvertDateTimeInt(System.DateTime time)
        {
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
            return (int)(time - startTime).TotalSeconds;
        }
        #endregion

        #region 生成当前时间戳
        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
        #endregion

        #region 加密解密
        public static byte[] bytesDESKey = Encoding.UTF8.GetBytes("hykjhykj");
        public static byte[] bytesDESIV = new byte[] { 18, 52, 86, 120, 144, 171, 205, 239 };
        //加密
        public static string EncryptDES(string strPlain)
        {

            try
            {
                DESCryptoServiceProvider desEncrypt = new DESCryptoServiceProvider();
                MemoryStream msEncrypt = new MemoryStream();
                CryptoStream csEncrypt = new CryptoStream(msEncrypt, desEncrypt.CreateEncryptor(bytesDESKey, bytesDESIV), CryptoStreamMode.Write);

                byte[] bytesPlain = Encoding.UTF8.GetBytes(strPlain);//明文
                csEncrypt.Write(bytesPlain, 0, bytesPlain.Length);
                csEncrypt.FlushFinalBlock();
                csEncrypt.Close();

                byte[] bytesCipher = msEncrypt.ToArray();
                msEncrypt.Close();
                return Convert.ToBase64String(bytesCipher);
            }
            catch (Exception e)
            {
                return "";
            }
        }
        //解密
        public static string DecryptDES(string strCipher)
        {
            try
            {

                byte[] bytesCipher = Convert.FromBase64String(strCipher);

                DESCryptoServiceProvider desDecrypt = new DESCryptoServiceProvider();
                MemoryStream msDecrypt = new MemoryStream();//new MemoryStream(bytesCipher)
                CryptoStream csDecrypt = new CryptoStream(msDecrypt, desDecrypt.CreateDecryptor(bytesDESKey, bytesDESIV), CryptoStreamMode.Write);//Read

                csDecrypt.Write(bytesCipher, 0, bytesCipher.Length);
                csDecrypt.FlushFinalBlock();
                string strPlainText = Encoding.UTF8.GetString(msDecrypt.ToArray());

                //srDecrypt.Close();
                csDecrypt.Close();
                msDecrypt.Close();
                //返回明文
                return strPlainText;
            }
            catch (Exception)
            {
                return "";
            }

        }
        #endregion

        #region 取得13位不重复的编码
        //为了防止并发 Sleep 1
        public static string GetRandomStr13()
        {
            System.Threading.Thread.Sleep(1);
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
        #endregion

        #region 转移json 为 list
        public static List<T> JSONStringToList<T>(string JsonStr)
        {

            JavaScriptSerializer Serializer = new JavaScriptSerializer();

            List<T> objs = Serializer.Deserialize<List<T>>(JsonStr);

            return objs;

        }
        #endregion

        #region 替换In这种特殊字符串
        public static string AddSqlYHString(string str)
        {
            if (!string.IsNullOrWhiteSpace(str))
            {
                return "'" + str.TrimEnd(',').Replace(",", "','") + "'";
            }
            return "";
        }
        #endregion

        public static string Modfnm(string fileDir, string no, string onm, string nnm)
        {
            try
            {
                String[] files = Directory.GetFiles(fileDir);
                foreach (String filename in files)
                {
                    //最后一个"\"
                    int lastpath = filename.LastIndexOf("\\");
                    //最后一个"."
                    int lastdot = filename.LastIndexOf(".");
                    // 纯文件名字长度
                    int length = lastdot - lastpath - 1;
                    // 文件目录字符串 xx\xx\xx\
                    String beginpart = filename.Substring(0, lastpath + 1);
                    //  纯文件名字
                    String namenoext = filename.Substring(lastpath + 1, length);
                    //   扩展名
                    String ext = filename.Substring(lastdot);

                    String namenew = namenoext.Replace(onm, nnm);

                    String fullnewname = beginpart + namenew + ext;
                    // 改名
                    File.Move(filename, fullnewname);

                    //log
                    //this.listBoxLog.Items.Add(namenoext + "--->" + namenew);
                    //this.listBoxLog.SelectedIndex = this.listBoxLog.Items.Count - 1;

                }
                return "1";
            }
            catch
            {
                return "0";
            }
        }
        #region MD5加密算法,加密后小写
        public static string GetMD5(string s)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] t = md5.ComputeHash(Encoding.GetEncoding("gb2312").GetBytes(s));
            StringBuilder sb = new StringBuilder(32);
            for (int i = 0; i < t.Length; i++)
            {
                sb.Append(t[i].ToString("x").PadLeft(2, '0'));
            }
            return sb.ToString();
        }
        #endregion

        public static DataSet ExcelToDataSet(string fullfilename)
        {
            //string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + fullfilename + ";" + "Extended Properties=Excel 8.0;";


            //string strConn = "Provider=Microsoft.Jet.OleDb.4.0;" + "data source=" + Server.MapPath("ExcelFiles/MyExcelFile.xls") + ";Extended Properties='Excel 8.0; HDR=Yes; IMEX=1'"; //此连接只能操作Excel2007之前(.xls)文件
            string strConn = "Provider=Microsoft.Ace.OleDb.12.0;" + "data source=" + fullfilename + ";Extended Properties='Excel 12.0; HDR=Yes; IMEX=1'"; //此连接可以操作.xls与.xlsx文件 (支持Excel2003 和 Excel2007 的连接字符串)
            //备注： "HDR=yes;"是说Excel文件的第一行是列名而不是数据，"HDR=No;"正好与前面的相反。
            //      "IMEX=1 "如果列中的数据类型不一致，使用"IMEX=1"可必免数据类型冲突。 

            OleDbConnection conn = new OleDbConnection(strConn);
            conn.Open();
            string strExcel = "";
            OleDbDataAdapter myCommand = null;
            DataSet ds = null;
            strExcel = "select * from [sheet1$]";
            myCommand = new OleDbDataAdapter(strExcel, strConn);
            ds = new DataSet();
            myCommand.Fill(ds, "table1");
            return ds;
        }

        public static int FileSave(HttpPostedFileBase file, string file_name)
        {

            try
            {
                //目录路径
                var FoldPath = System.Web.HttpContext.Current.Server.MapPath("~/ExcelFile/");
                //var FoldPath = System.Web.HttpContext.Current.Server.MapPath(file_name);
                //如果文件夹不存在就创建 
                if (!Directory.Exists(FoldPath))
                {
                    Directory.CreateDirectory(FoldPath);
                }
                //后缀

                //保存文件
                file.SaveAs(file_name);
                //返回
                return 1; //代表保存没有异常
            }
            catch (Exception E)
            {
                return 0; //有异常
            }

        }

    }

    #region timeConverter
    public class IntDateTimeConverter : DateTimeConverterBase
    {
        public string DateTimeFormat { get; set; }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType != JsonToken.Integer)
            {
                throw new Exception(String.Format("日期格式错误,got {0}.", reader.TokenType));
            }
            var ticks = (long)reader.Value;
            var date = new DateTime(1970, 1, 1);
            date = date.AddSeconds(ticks);
            return date;
        }
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            long ticks;
            if (value is DateTime)
            {
                var epoc = new DateTime(1970, 1, 1);
                var delta = ((DateTime)value) - epoc;
                if (delta.TotalSeconds < 0)
                {
                    if (delta.TotalSeconds == -2208988800) //1900-01-01 00:00:00.000
                    {

                    }
                    // throw new ArgumentOutOfRangeException("时间格式错误.1");
                }
                ticks = (long)delta.TotalSeconds;
            }
            else
            {
                throw new Exception("时间格式错误.2");
            }
            writer.WriteValue(ticks);
        }
    }
    #endregion
}

